package com.haixee.parkdemo.gateway.security;

import com.haixee.parkdemo.common.entity.AuthData;
import com.haixee.parkdemo.common.exception.BusinessException;
import com.haixee.parkdemo.common.response.CommonResEnum;
import com.haixee.parkdemo.gateway.constants.WebConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

@Component
@Slf4j
public class DefaultAuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {

    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> authentication, AuthorizationContext authorizationContext) {
        return authentication.map(auth -> {

            if (auth.getPrincipal() == null) {
                return new AuthorizationDecision(false);
            }

            AuthData authData = (AuthData) auth.getPrincipal();

            try {
                if (!authData.getAuth()) {
                    return new AuthorizationDecision(false);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }


            authorizationContext.getExchange().getAttributes().put(WebConstants.AUTH_DATA, auth.getPrincipal());

            return new AuthorizationDecision(true);
        });
    }

    @Override
    public Mono<Void> verify(Mono<Authentication> authentication, AuthorizationContext object) {
        return check(authentication, object)
                .filter(AuthorizationDecision::isGranted)
                .switchIfEmpty(Mono.defer(() -> Mono.error(new BusinessException(CommonResEnum.PERMISSION_DENIED))))
                .flatMap(d -> Mono.empty());
    }
}
